package org.opensuse.bs.ui.actions;

import java.io.File;
import java.util.Set;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.ITreeSelection;
import org.eclipse.jface.viewers.TreePath;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.FileDialog;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.List;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.IObjectActionDelegate;
import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.ui.dialogs.ContainerSelectionDialog;
import org.opensuse.bs.ui.BSUIPlugin;

    
public class BuildAction implements IObjectActionDelegate {
	private Object[] objs;
	
	private class BuildDialog extends Dialog {
		private Combo combo;
		private Text alternativePrj;
		private Text preferDir;
		private Text keepDir;
		private List extraPkg;
		private Group buildRootGroup;
		private Button[] archButtons;
		private Button[] optButtons;
		private String[] opts = {"--baselibs ","--debuginfo ","--local-package ",
				"--userootforbuild ","--no-verify ","--noinit ","--no-changelog ","--clean "};
		
		private void build(){
			int index = combo.getSelectionIndex();
			if(index == -1) {
				MessageDialog.openInformation(null, 
						"Missing platform", 
						"Please specify a platform for build");
			}
			final String platform = combo.getItem(index);
			
			boolean i586 = archButtons[0].getSelection();
			boolean x86_64 = archButtons[1].getSelection();
			if(!i586 && !x86_64) {
				MessageDialog.openInformation(null, 
						"Missing arch", 
						"Please specify an architecture for build");
			}
			String tmp="";
			if(i586)tmp="i586";
			if(x86_64)tmp="x86_64";
			final String arch = tmp;
			
			tmp="";
			for(int i=0;i<optButtons.length;i++) {
				if(optButtons[i].getSelection()) {
					tmp+=opts[i];
				}
			}
			final String optPart = tmp;
			
			tmp="";
			String[] files = extraPkg.getItems();
			if(files.length != 0) {
				for(String file:files) {
					tmp=tmp+"-x "+file+" ";
				}
			}
			final String extra = tmp;
			
			tmp="";
			String alterPrj = alternativePrj.getText().trim();
			String prefer = preferDir.getText().trim();
			String keep = keepDir.getText().trim();
			if(alterPrj.length() != 0) {
				tmp = tmp+"--alternative-project="+alterPrj+" ";
			}
			if(prefer.length() != 0) {
				tmp = tmp+"--prefer-pkgs="+prefer+" ";
			}
			if(keep.length() != 0) {
				tmp = tmp+"--keep-pkgs="+keep+" ";
			}
			final String others = tmp;
			
			Job job = new Job("Build projects") {
				public IStatus run(IProgressMonitor monitor) {
					monitor.beginTask("Building...", objs.length);
					try {
						for(Object obj : objs) {
							if (monitor.isCanceled())
								return Status.CANCEL_STATUS;
							IFile file = (IFile) obj;
							monitor.subTask("Building "+file.getName());
							if(!file.exists()) {
								throw new Exception("File does not exist!");
							}
							File dir = new File(file.getParent().getLocation().toOSString());
							String cmd = "osc build "+optPart+others+extra+platform+" "+arch+" "+file.getName();
							String command = "xterm -hold -e "+cmd;
							Runtime.getRuntime().exec(command, null, dir);
							monitor.worked(1);
						}
					}catch(Exception e) {
						e.printStackTrace();
					}
					finally {
						monitor.done();
					}
					return Status.OK_STATUS;
				}
			};
			job.schedule();
		}
		
		private void handleBrowse(Text containerText) {
			ContainerSelectionDialog dialog = new ContainerSelectionDialog(
					getShell(), ResourcesPlugin.getWorkspace().getRoot(), false,
					"Select new file container");
			if (dialog.open() == ContainerSelectionDialog.OK) {
				Object[] result = dialog.getResult();
				if (result.length == 1) {
					containerText.setText(((Path) result[0]).toString());
				}
			}
		}
		
		public BuildDialog(Shell parentShell) {
			super(parentShell);
		}
		
		protected void configureShell(Shell newShell) {
			super.configureShell(newShell);
		   newShell.setText("OSC Build Info");
		   }
		
		protected Control createDialogArea(Composite parent) {
			Composite client = new Composite(parent, SWT.NONE);
			GridLayout layout = new GridLayout();
			layout.numColumns = 3;
			client.setLayout(layout);
			
			/*General Info group*/
			Group group1 = new Group(client, SWT.BORDER);
			group1.setText("General");
			GridData gd = new GridData();
			gd.horizontalSpan = 3;
			gd.grabExcessHorizontalSpace = true;
			gd.horizontalAlignment = SWT.FILL;
			group1.setLayoutData(gd);
			layout = new GridLayout();
			layout.numColumns = 3;
			group1.setLayout(layout);			
			Label label1 = new Label(group1, SWT.NONE);
			label1.setText("Platform: ");
			combo = new Combo(group1, SWT.SIMPLE);
			gd = new GridData();
			combo.setLayoutData(gd);
			gd.horizontalAlignment = SWT.FILL;
			gd.grabExcessHorizontalSpace = true;
			gd.horizontalSpan = 2;
			Set<String> distros = BSUIPlugin.getDefault().getDistros().keySet();
			for(String distro : distros) {
				combo.add(distro);
			}
			Label label2 = new Label(group1, SWT.NONE);
			label2.setText("Architecture: ");
			archButtons = new Button[2];
			archButtons[0] = new Button(group1, SWT.RADIO);
			archButtons[0].setText("i586");
			archButtons[1] = new Button(group1, SWT.RADIO);
			archButtons[1].setText("x86_64");
			
			/*Build Option group*/
			Group group2 = new Group(client, SWT.BORDER);
			group2.setText("Build Option(Optional)");
			gd = new GridData();
			gd.horizontalSpan = 3;
			gd.grabExcessHorizontalSpace = true;
			gd.horizontalAlignment = SWT.FILL;
			group2.setLayoutData(gd);
			layout = new GridLayout();
			group2.setLayout(layout);
			layout.numColumns = 3;
			
			Label label3 = new Label(group2, SWT.NONE);
			label3.setText("Alternative Project: ");
			alternativePrj = new Text(group2, SWT.BORDER|SWT.SINGLE);
			this.alternativePrj.setToolTipText("If the project of the package " +
					"doesn't exist on the server please provide an exsiting project name here.");
			gd = new GridData();
			alternativePrj.setLayoutData(gd);
			gd.grabExcessHorizontalSpace = true;
			gd.horizontalAlignment=SWT.FILL;
			gd.horizontalSpan=2;
			
			Label label4 = new Label(group2, SWT.NONE);
			label4.setText("Aim Dir");
			keepDir = new Text(group2, SWT.BORDER|SWT.SINGLE);
			keepDir.setToolTipText(" Save built packages into this directory");
			gd = new GridData(GridData.FILL_HORIZONTAL);
			keepDir.setLayoutData(gd);
			Button button = new Button(group2, SWT.PUSH);
			button.setText("Browse...");
			button.addSelectionListener(new SelectionAdapter() {
				public void widgetSelected(SelectionEvent e) {
					handleBrowse(keepDir);
				}
			});
			gd = new GridData();
			button.setLayoutData(gd);
			gd.widthHint = 80;
			
			optButtons = new Button[8];
			for(int i=0;i<7;i++) {
				optButtons[i] = new Button(group2, SWT.CHECK);
				gd = new GridData(GridData.FILL_HORIZONTAL);
				optButtons[i].setLayoutData(gd);
				gd.horizontalSpan = 3;
			}
			optButtons[0].setText("Create -32bit/-64bit/-x86 rpms for other architectures");
			optButtons[1].setText("Also build debuginfo sub-packages");
			optButtons[2].setText("Build a package which does not exist on the server");
			optButtons[3].setText("Run build as root");
			optButtons[4].setText("Skip signature verification of packages used for build");
			optButtons[5].setText("Skip initialization of build root and start with build immediately.");
			optButtons[5].addSelectionListener(new SelectionAdapter() {
				public void widgetSelected(SelectionEvent e) {
					Group group = BuildDialog.this.buildRootGroup;
					if(optButtons[5].getSelection()) {
						group.setEnabled(false);
						Control[] children = group.getChildren();
						for(Control child:children) {
							child.setEnabled(false);
						}
					}
					else {
						group.setEnabled(true);
						Control[] children = group.getChildren();
						for(Control child:children) {
							child.setEnabled(true);
						}
					}
				}
			});
			optButtons[6].setText("Don't update the package changelog from a changes file");
			
			/*Configure Build Root group*/
			buildRootGroup = new Group(client, SWT.BORDER);
			buildRootGroup.setText("Configure Build Root(Optional)");
			gd = new GridData();
			gd.horizontalSpan = 3;
			gd.grabExcessHorizontalSpace = true;
			gd.horizontalAlignment = SWT.FILL;
			buildRootGroup.setLayoutData(gd);
			layout = new GridLayout();
			layout.numColumns = 3;
			buildRootGroup.setLayout(layout);
			
			Label label5 = new Label(buildRootGroup, SWT.NONE);
			label5.setText("Source Dir:");
			preferDir = new Text(buildRootGroup, SWT.BORDER|SWT.SINGLE);
			preferDir.setToolTipText("Prefer packages from this directory when installing the build-root");
			gd = new GridData(GridData.FILL_HORIZONTAL);
			preferDir.setLayoutData(gd);
			Button button2 = new Button(buildRootGroup, SWT.PUSH);
			button2.setText("Browse...");
			button2.addSelectionListener(new SelectionAdapter() {
				public void widgetSelected(SelectionEvent e) {
					handleBrowse(preferDir);
				}
			});
			gd = new GridData();
			button2.setLayoutData(gd);
			gd.widthHint = 80;
			
			optButtons[7] = new Button(buildRootGroup, SWT.CHECK);
			optButtons[7].setText("Delete old build root before initializing it");
			gd = new GridData(GridData.FILL_HORIZONTAL);
			optButtons[7].setLayoutData(gd);
			gd.horizontalSpan = 3;
			
			Label label6 = new Label(buildRootGroup, SWT.NONE);
			label6.setText("Extra Packages:");
			gd = new GridData(GridData.FILL_HORIZONTAL);
			label6.setLayoutData(gd);
			gd.horizontalSpan=3;
			extraPkg = new List(buildRootGroup, SWT.BORDER|SWT.MULTI|SWT.H_SCROLL|SWT.V_SCROLL);
			extraPkg.setToolTipText("Add the packages in this list when installing the build-root");
			gd = new GridData(GridData.FILL_HORIZONTAL);
			extraPkg.setLayoutData(gd);
			gd.horizontalSpan=2;
			gd.verticalSpan = 2;
			gd.heightHint = 100;
			Button add = new Button(buildRootGroup, SWT.PUSH);
			add.setText("Add");
			add.addSelectionListener(new SelectionAdapter() {
				public void widgetSelected(SelectionEvent e) {
					FileDialog dialog = new FileDialog(getShell());
					String item = dialog.open();
					if(item != null) {
						BuildDialog.this.extraPkg.add(item);
					}
				}
			});
			gd = new GridData();
			add.setLayoutData(gd);
			gd.widthHint = 80;
			Button remove = new Button(buildRootGroup, SWT.PUSH);
			remove.setText("Remove");
			remove.addSelectionListener(new SelectionAdapter() {
				public void widgetSelected(SelectionEvent e) {
					List list = BuildDialog.this.extraPkg;
					if(list.getSelectionCount() != 0) {
						list.remove(list.getSelectionIndices());
					}
				}
			});
			gd = new GridData();
			remove.setLayoutData(gd);
			gd.widthHint = 80;
			
			return client;
		}
		
		public void createButtonsForButtonBar(Composite parent) {
			GridLayout layout = new GridLayout();
			parent.setLayout(layout);
			layout.numColumns = 3;
			
			GridData gd = new GridData();
			Button button1 = new Button(parent, SWT.PUSH);
			button1.setText("Build");
			button1.setLayoutData(gd);
			gd.widthHint = 100;
			button1.addSelectionListener(new SelectionAdapter() {
				public void widgetSelected(SelectionEvent e) {
					build();
					close();
				}
			});
			
			gd = new GridData();
			Button button2 = new Button(parent, SWT.PUSH);
			button2.setText("Cancel");
			button2.setLayoutData(gd);
			gd.widthHint = 100;
			button2.addSelectionListener(new SelectionAdapter() {
				public void widgetSelected(SelectionEvent e) {
					BuildDialog.this.close();
				}
			});
		}
	}
	
	public void setActivePart(IAction action, IWorkbenchPart targetPart) {
		objs = new Object[0];
	}
	
	public void run(IAction action) {
		Dialog dialog = new BuildDialog(null);
		dialog.open();
	}
	
	public void selectionChanged(IAction action, ISelection selection) {
		if(selection instanceof ITreeSelection) {
			TreePath[] paths = ((ITreeSelection) selection).getPaths();
			if(paths.length != 0) {
				objs = new Object[paths.length];
				for(int i=0;i<paths.length;i++) {
					objs[i] = paths[i].getLastSegment();
				}
			}
		}
	}
}
